package item;


import gnu.trove.map.hash.TIntObjectHashMap;
import gnu.trove.map.hash.TLongIntHashMap;
import idGen.BaseValueIntIdGenerator;
import idGen.IntIdGenerator;
import idGen.LongIdGenerator;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;

import MemoryDB.YuanTable;
import Public.PlayerPublicFun;
import Public.ServerActor;
import util.Time;

	
public  class DefaultItemService implements ItemService {
	protected TIntObjectHashMap<ItemTemplate> templates = new TIntObjectHashMap<ItemTemplate>();
	//protected TIntObjectHashMap<SuiteEffects> suites = new TIntObjectHashMap<SuiteEffects>();
	protected LongIdGenerator id_gen = null;
	protected IntIdGenerator instanceId_gen = null;
	
	protected static final String SEQ_NAME = "itemid";
	protected static final int INSTANCE_BASE_VALUE = 0;

	protected ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	protected ReadLock readLock = lock.readLock();
	protected WriteLock writeLock = lock.writeLock();
	protected TLongIntHashMap id2instanceid = new TLongIntHashMap(10000, 0.5f, -1, -1);
	protected int imoneycardTemplateId = -1;
	
	
	@Override
	public GameItem createGameItem(ItemTemplate template) {
		GameItem item = null;
		long id = GameItem.GNERAL_ID;
		int instanceId = GameItem.GENERAL_INSTANCEID;
		if(template.isNewInstance()){
			id = id_gen.next();
			instanceId =  createNewInstanceId(id);
		}
		item = createGameItem(template, id, instanceId);
		setObsoleteTime(item);
		return item;
	}
	
	public GameItem createGameItem(ItemTemplate template,int instanceId)
	{
		return createGameItem(template, GameItem.GENERAL_INSTANCEID, instanceId);
	}
	
	@Override
	public GameItem createGameItem(ItemTemplate template,long id){
		int instanceId = GameItem.GENERAL_INSTANCEID;
		if(template.isNewInstance()){
			instanceId = getInstanceId(id);
			if(instanceId == -1){
				instanceId = createNewInstanceId(id);
			}
		}
		return createGameItem(template, id, instanceId);
	}
	
	protected GameItem createGameItem(ItemTemplate template, long id, int instanceId){
		if(template instanceof EquipmentTemplate){
			return createEquipment(template, id, instanceId);
		}else{
			return createNormalGameItem(template, id, instanceId);
		}
	}
	
	protected GameItem createNormalGameItem(ItemTemplate template, long id, int instanceId){
		return new BaseItem(template, id, instanceId);
	}
	
	
	public Equipment createEquipment(ItemTemplate template, long id , int instanceId)
	{
		return new DefaultEquipment(template, id, instanceId);
	}
	
	protected void setObsoleteTime(GameItem item){
		ItemTemplate template = item.getTemplate();
		if(template.getObsoleteType() != 0){
			if(template.getObsoleteType() == 1){
				item.setObsoleteTime(template.getObsoleteTime());
			}
			else if(template.getObsoleteType() == 2){
				item.setObsoleteTime((int)(Time.currDate.getTime()/1000+template.getObsoleteTime()));
			}
		}
	}
	
	public int getInstanceId(long id) {
		readLock.lock();
		try {
			return id2instanceid.get(id);
		} finally {
			readLock.unlock();
		}
	}
	
	public int createNewInstanceId(long id){
		writeLock.lock();
		try{
			int instanceId = instanceId_gen.next();
			id2instanceid.put(id, instanceId);
			return instanceId;
		}finally{
			writeLock.unlock();
		}
	}
	

	

	@Override
	public ItemTemplate getItemTemplate(int id) {
		return templates.get(id);
	}

	@Override
	public String getId() {
		return "ItemService";
	}

	@Override
	public void shutdown() {
		
	}

	@Override
	public void startup() throws Exception {
		
		loadEquipTemplates();
		//myadd
		loadPropTemplates();
		//loadSuiteConfig(dataService.data.getDataListByType(com.pip.game.data.equipment.SuiteConfig.class));
		//SleepyCat.openSequence(SEQ_NAME);
		//id_gen = new ServerPersistLongIdGenerator(Platform.getServerId(), 3, SEQ_NAME);
		instanceId_gen = new BaseValueIntIdGenerator(INSTANCE_BASE_VALUE);
		//imoneycardTemplateId = Platform.getConfiguration().getInt("imoneycard");
	}
	
	/*protected void loadSuiteConfig(List ts){
		for(Object o:ts) {
			SuiteConfig config = (SuiteConfig)o;
			SuiteEffects effects = translateSuiteConfig(config);
			suites.put(effects.getID(), effects);
		}
	}*/
	
	protected void loadEquipTemplates() throws Exception
	{
		ServerActor<String, YuanTable> bfData = PlayerPublicFun.getEquipmentData();
		for(Map.Entry<String, YuanTable> bfItems: bfData.entrySet())
		{
			EquipmentTemplate template = loadEquipTemplate(bfItems);
			templates.put(template.getId(), template);
		}
	}
	
	protected void loadPropTemplates() throws Exception
	{
		ServerActor<String, YuanTable> bfData = PlayerPublicFun.PubGameItemForItemID;
		for(Map.Entry<String, YuanTable> bfItems: bfData.entrySet())
		{
			int id = Integer.parseInt(bfItems.getKey());
			DefaultItemTemplate it = new DefaultItemTemplate(id);
			it.setMaxCount(100);
			
			templates.put(it.getId(), it);
		}
	}
	
	protected EquipmentTemplate loadEquipTemplate(Map.Entry<String, YuanTable> equ)
	{
		int id = Integer.parseInt(equ.getKey());
		DefaultEquipmentTemplate it = new DefaultEquipmentTemplate(id);
        //buildBaseItemTemplate(it,equ);
        //it.setPart(equ.place);
		//todo it set
		it.setMaxCount(1);
        return it;
	}
	
	protected ItemTemplate loadItemTemplate(Map.Entry<String, YuanTable> item) {
		int id = Integer.parseInt(item.getKey());
		DefaultItemTemplate it = new DefaultItemTemplate(id);
		//buildBaseItemTemplate(it,item);
		//todo it set
		return it;
	}
	
	/*protected void buildBaseItemTemplate(DefaultItemTemplate it,Map.Entry<String, YuanTable> item)
	{
		if (item.bind == Item.BIND_NO)
		{
			it.setBindType(ItemTemplate.BIND_NO);
		}
		else if (item.bind == Item.BIND_EQUIPMENT)
		{
			it.setBindType(ItemTemplate.BIND_EQUED);
		} 
		else if (item.bind == Item.BIND_PICK_UP) 
		{
			it.setBindType(ItemTemplate.BIND_REWARD);
		}
		
		it.setAdditionalCondition(item.additionalCondition);
		it.setDesc(item.description);
		it.setGroup(item.type);
		it.setCategory(item.mainType);
		it.setIcon(item.iconIndex);
		it.setLevel(item.level);
		it.setMaxCount(item.addition);
		it.setName(item.title);
		it.setNewInstance(item.instance);
		if (item.sale)
			it.setPrice(item.price);
		else
			it.setPrice(-1);
		it.setQuality(item.quality);
		it.setQuestItem(item.taskFlag);
		it.setUseLevel(item.playerLevel);
		if (item.available == Item.AVAILABLE_NO)
		{
			it.setUseType(ItemUseType.NOUSETYPE);
		} 
		else
		{
			ItemUseType useType = new ItemUseType();
			if (item.available == Item.AVAILABLE_UN_BATTLE)
				useType.occasion = ItemUseType.OCCASION_NOBATTLE;
			else if (item.available == Item.AVAILABLE_BATTLE) {
				useType.occasion = ItemUseType.OCCASION_BATTLE;
			} else if (item.available == Item.AVAILABLE_EVER) {
				useType.occasion = ItemUseType.OCCASION_ALL;
			}
			if (item.area == Item.AREA_UN_DEFINE) {
				useType.targetType = ItemUseType.TARGET_NOTARGET;
			} else if (item.area == Item.AREA_SELF) {
				useType.targetType = ItemUseType.TARGET_SELF;
			} else if (item.area == Item.AREA_TEAM) {
				useType.targetType = ItemUseType.TARGET_PARTY;
			} else if (item.area == Item.AREA_ENEMY) {
				useType.targetType = ItemUseType.TARGET_ENEMY;
			} else if (item.area == Item.AREA_ALL) {
				useType.targetType = ItemUseType.TARGET_ALL;
			}
			useType.clazz = item.useClazz;
			useType.confirmString = item.useConfirm==null?"":item.useConfirm;
			useType.consume = item.waste;
			useType.coolDownId = item.coldDownGroup;
			useType.coolDownTime = item.coldDownTime;
			useType.spellTime = item.schedule;
			useType.distance = item.distance;
			if (useType.distance != -1) {
				useType.distance = item.distance * 8;
			}
			it.setUseType(useType);
		}
	}*/
	
	
	
	protected TIntObjectHashMap<Marshaller> id2marshaller = new TIntObjectHashMap<Marshaller>();
	protected Map<Class<? extends Marshaller>, Marshaller> class2marshaller = new HashMap<Class<? extends Marshaller>, Marshaller>();

	protected TIntObjectHashMap<Serializer> id2serializer = new TIntObjectHashMap<Serializer>();
	protected Map<Class<? extends Serializer>, Serializer> class2serializer = new HashMap<Class<? extends Serializer>, Serializer>();

	public void registerMarshaller(Marshaller marshaller) {
		id2marshaller.put(marshaller.getId(), marshaller);
		class2marshaller.put(marshaller.getClass(), marshaller);
	}
	
	public void registerSerializer(Serializer serializer){
		id2serializer.put(serializer.getId(), serializer);
		class2serializer.put(serializer.getClass(), serializer);
	}
	
	public Marshaller getMarshaller(Class<? extends Marshaller> clazz){
		return class2marshaller.get(clazz);
	}
	
	public Serializer getSerializer(Class<? extends Serializer> clazz){
		return class2serializer.get(clazz);
	}
	
	public Marshaller getMarshaller(int id){
		return id2marshaller.get(id);
	}
	
	public Serializer getSerializer(int id){
		return id2serializer.get(id);
	}
	
    @Override
    public ItemTemplate getIMoneyCardTemplate(){
    	if(imoneycardTemplateId != -1)
    		return getItemTemplate(imoneycardTemplateId);
    	return null;
    }
    
    @Override
    public byte[] toClientBytes(ItemTemplate template){
    	return BaseItem.toClientBytes(template);
    }
}
